﻿/*************************************
 * Creator:SW-PeiYang
 * DateTime:2023/12/8 9:06:31
 * Description:<Description>
 * CopyRight:中广核研究院有限公司
 * ***********************************/

using Cpjit.SunnyPaine.Toolkit.Net.Sockets.Util;
using System;
using System.Net;
using System.Net.Sockets;

namespace Cpjit.SunnyPaine.Toolkit.Net.Sockets.Model
{
    /// <summary>
    /// TCP客户端会话。
    /// </summary>
    public class SocketSession
    {
        #region 公共属性（程序集内部的）
        /// <summary>
        /// 缓存大小。
        /// </summary>
        internal int BufferSize { get; }
        /// <summary>
        /// 接收到的数据量。
        /// </summary>
        internal int ReceivedCount { get; set; }
        /// <summary>
        /// 接收数据的缓存。
        /// </summary>
        internal byte[] Buffer { get; set; }
        #endregion


        #region 公共属性
        /// <summary>
        /// 客户端。如果本地是TCP客户端，则<see cref="Client"/>为本地客户端；如果本地是TCP服务端，则<see cref="Client"/>为远端客户端。
        /// </summary>
        public Socket Client { get; }
        /// <summary>
        /// 客户端Id。默认为 127.0.0.1:1234 格式的IP地址。
        /// </summary>
        public string ClientId { get; set; }
        /// <summary>
        /// 客户端IP地址。
        /// </summary>
        public string ClientIP { get; internal set; }
        /// <summary>
        /// 客户端端口。
        /// </summary>
        public int ClientPort { get; internal set; }
        /// <summary>
        /// IP端口。
        /// </summary>
        public string IPAddress
        {
            get { return $"{this.ClientIP}:{this.ClientPort}"; }
        }
        /// <summary>
        /// 最后接收到消息的时间。
        /// </summary>
        public DateTime LastReceiveTime { get; set; }
        #endregion


        #region 构造方法
        /// <summary>
        /// 使用指定的参数创建<see cref="SocketSession"/>的实例。
        /// </summary>
        /// <param name="ip"></param>
        /// <param name="port"></param>
        /// <param name="bufferSize"></param>
        public SocketSession(string ip, int port, int bufferSize)
        {
            this.ClientIP = ip;
            this.ClientPort = port;
            this.BufferSize = bufferSize;
            this.Buffer = new byte[bufferSize];
        }

        /// <summary>
        /// 使用指定的参数创建<see cref="SocketSession"/>的实例。
        /// </summary>
        /// <param name="client">TCP客户端对象。</param>
        public SocketSession(Socket client) : this(client, ushort.MaxValue)
        { }

        /// <summary>
        /// 使用指定的参数创建<see cref="SocketSession"/>的实例。
        /// </summary>
        /// <param name="client">TCP客户端对象。</param>
        /// <param name="bufferSize">接收数据的缓存大小。</param>
        public SocketSession(Socket client, int bufferSize)
        {
            this.Client = client;
            EndPoint endPoint = client.RemoteEndPoint;
            Tuple<string, int> ipport = endPoint.GetIpPort();
            this.ClientIP = ipport.Item1;
            this.ClientPort = ipport.Item2;
            this.ClientId = $"{ipport.Item1}:{ipport.Item2}";
            this.BufferSize = bufferSize;
            this.Buffer = new byte[bufferSize];
        }
        #endregion

        #region 公共方法
        /// <summary>
        /// 关闭会话。
        /// </summary>
        public void Close()
        {
            this.Client.Shutdown(SocketShutdown.Both);
            this.Client.Close(100);
        }

        /// <summary>
        /// 深拷贝<see cref="SocketSession"/>的值。
        /// </summary>
        /// <returns></returns>
        public SocketSession Deepclone()
        {
            SocketSession tmp = new SocketSession(this.Client, this.BufferSize)
            {
                ClientId = this.ClientId,
                LastReceiveTime = this.LastReceiveTime,
                ReceivedCount = this.ReceivedCount
            };
            this.Buffer.CopyTo(tmp.Buffer, 0);
            return tmp;
        }
        #endregion
    }
}
